package com.ecarx.vhaltests.hy11.testcases.climate;

import android.car.VehicleAreaSeat;
import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;


@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class HvacAutoOnTest extends VhalUnitTestBase {

    private static final String TAG = "HvacAutoOnTest";
    private static boolean halValueRow1;
    private static int halStatusRow1;
    private static boolean halValueRow1Right;
    private static int halStatusRow1Right;

    private static boolean halValueRow2;
    private static int halStatusRow2;
    private static boolean halValueRow2Right;
    private static int halStatusRow2Right;

    private static int halArea;

    private static final int HVAC_AUTO_ON = VehiclePropertyIds.HVAC_AUTO_ON;

    private static final int HVAC_AUTO_ON_AREA_ROW1 = VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_1_RIGHT;

    private static final int HVAC_AUTO_ON_AREA_ROW1_RIGHT = VehicleAreaSeat.SEAT_ROW_1_RIGHT;

    private static final int HVAC_AUTO_ON_AREA_ROW2 = VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER | VehicleAreaSeat.SEAT_ROW_2_RIGHT;
    private static final int HVAC_AUTO_ON_AREA_ROW2_RIGHT = VehicleAreaSeat.SEAT_ROW_2_RIGHT;
    private static final int SERVICE_ID_CLIMATE = 112;
    private static final int OP_ID_CLIMATE = 0xc8;
    private static final int LOCK_TIME = 100;

    final static Object lockRow1 = new Object();
    final static Object lockRow1Right = new Object();
    final static Object lockRow2 = new Object();
    final static Object lockRow2Right = new Object();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, HVAC_AUTO_ON, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig(OP_ID_CLIMATE);
        delay();
    }

    @Test
    public void testHvacAutoOnAvailable_01() {
        // 设置 空调Auto 不可用
        setHvacAutorOnAvail(3, 0, HVAC_AUTO_ON_AREA_ROW1);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW1, false);
        delay();

        setHvacAutorOnAvail(3, 0, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW1_RIGHT, false);
        delay();

    }

    @Test
    public void testHvacAutoOnAvailable_02() {
        // 设置 空调Auto 可用
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW1, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW1_RIGHT, true);
        delay();

    }


    @Test
    public void testHvacAutoOnRow1Get_01() {
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1);
        // 测试打开空调Auto后，获取空调状态
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW1, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW1_RIGHT, true);
        delay();
    }

    @Test
    public void testHvacAutoOnRow1Get_02() {
        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW1);
        // 测试关闭空调Auto后，获取空调状态
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW1, false);
        delay();

        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW1_RIGHT, false);
        delay();
    }

    @Test
    public void testHvacAutoOnRow1Set_01() {
        // 设置 空调Auto 可用
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1);
        // 测试打开空调Auto
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW1, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW1_RIGHT, true);
        delay();
    }

    @Test
    public void testHvacAutoOnRow1Set_02() {
        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW1);
        // 测试关闭空调Auto
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW1, false);
        delay();

        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW1_RIGHT);
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW1_RIGHT, false);
        delay();
    }

    @Test
    public void testHvacAutoOnRow2Available_01() {
        // 设置 空调Auto 不可用
        setHvacAutorOnAvail(3, 0, HVAC_AUTO_ON_AREA_ROW2);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW2, false);
        delay();

        setHvacAutorOnAvail(3, 0, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW2_RIGHT, false);
        delay();
    }

    @Test
    public void testHvacAutoOnRow2Available_02() {
        // 设置 空调Auto 可用
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW2, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnAvailable(HVAC_AUTO_ON_AREA_ROW2_RIGHT, true);
        delay();
    }


    @Test
    public void testHvacAutoOnRow2Get_01() {
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2);
        // 测试打开空调Auto后，获取空调状态
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW2, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW2_RIGHT, true);
        delay();
    }

    @Test
    public void testHvacAutoOnRow2Get_02() {
        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW2);
        // 测试关闭空调Auto后，获取空调状态
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW2, false);
        delay();

        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnGet(HVAC_AUTO_ON_AREA_ROW2_RIGHT, false);
        delay();
    }

    @Test
    public void testHvacAutoOnRow2Set_01() {
        // 设置 空调Auto 可用
        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2);
        // 测试打开空调Auto
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW2, true);
        delay();

        setHvacAutorOnAvail(1, 0, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW2_RIGHT, true);
        delay();
    }

    @Test
    public void testHvacAutoOnRow2Set_02() {
        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW2);
        // 测试关闭空调Auto
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW2, false);
        delay();

        setHvacAutorOnAvail(1, 1, HVAC_AUTO_ON_AREA_ROW2_RIGHT);
        testHvacAutoOnSet(HVAC_AUTO_ON_AREA_ROW2_RIGHT, false);
        delay();
    }


    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                halArea = carPropertyValue.getAreaId();
                Log.d(TAG, "HVAC_AUTO_ON onChangeEvent value: propertyId ：" + carPropertyValue.getPropertyId()
                        + " propertyValue：" + carPropertyValue.getValue() + " status: " + carPropertyValue.getStatus()
                        + " area：" + carPropertyValue.getAreaId());
                if (halArea == HVAC_AUTO_ON_AREA_ROW1) {
                    halValueRow1 = (boolean) carPropertyValue.getValue();
                    halStatusRow1 = carPropertyValue.getStatus();
                    synchronized (lockRow1) {
                        lockRow1.notify();
                        Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock notify lockRow1");
                    }
                } else if (halArea == HVAC_AUTO_ON_AREA_ROW2) {
                    halValueRow2 = (boolean) carPropertyValue.getValue();
                    halStatusRow2 = carPropertyValue.getStatus();
                    synchronized (lockRow2) {
                        lockRow2.notify();
                        Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock notify lockRow2");
                    }
                } else if (halArea == HVAC_AUTO_ON_AREA_ROW1_RIGHT) {
                    halValueRow1Right = (boolean) carPropertyValue.getValue();
                    halStatusRow1Right = carPropertyValue.getStatus();
                    synchronized (lockRow1Right) {
                        lockRow1Right.notify();
                        Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock notify lockRow1Right");
                    }
                } else if (halArea == HVAC_AUTO_ON_AREA_ROW2_RIGHT) {
                    halValueRow2Right = (boolean) carPropertyValue.getValue();
                    halStatusRow2Right = carPropertyValue.getStatus();
                    synchronized (lockRow2Right) {
                        lockRow2Right.notify();
                        Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock notify lockRow2Right");
                    }
                }
                Log.d(TAG, "HVAC_AUTO_ON onChangeEvent halValueRow1 :" + halValueRow1 + " halValueRow2：" + halValueRow2
                        + " halValueRow1Right：" + halValueRow1Right + " halValueRow2Right：" + halValueRow2Right);

            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };


    public void lockWait(int area) {
        try {
            if (area == HVAC_AUTO_ON_AREA_ROW1) {
                synchronized (lockRow1) {
                    Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock wait lockRow1");
                    lockRow1.wait(LOCK_TIME);
                }
            } else if (area == HVAC_AUTO_ON_AREA_ROW2) {
                synchronized (lockRow2) {
                    Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock wait lockRow2");
                    lockRow2.wait(LOCK_TIME);
                }
            } else if (area == HVAC_AUTO_ON_AREA_ROW1_RIGHT) {
                synchronized (lockRow1Right) {
                    Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock wait lockRow1Right");
                    lockRow1Right.wait(LOCK_TIME);
                }
            } else if (area == HVAC_AUTO_ON_AREA_ROW2_RIGHT) {
                synchronized (lockRow2Right) {
                    Log.d(TAG, "HVAC_AUTO_ON onChangeEvent Lock wait lockRow2Right");
                    lockRow2Right.wait(LOCK_TIME);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public void testHvacAutoOnAvailable(int area, boolean avail) {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(HVAC_AUTO_ON, area);
        Log.d(TAG, "testHvacAutoOnAvailable isAvail：" + isAvail);
        Assert.assertEquals(avail, isAvail);
    }

    public void testHvacAutoOnSet(int area, boolean value) {
        Log.d(TAG, "testHvacAutoOnSet area：" + area + " value: " + value);
        mCarPropertyMgr.setBooleanProperty(HVAC_AUTO_ON, area, value);
        lockWait(area);
        if (area == HVAC_AUTO_ON_AREA_ROW1) {
            Assert.assertEquals(value, halValueRow1);
        } else if (area == HVAC_AUTO_ON_AREA_ROW2) {
            Assert.assertEquals(value, halValueRow2);
        } else if (area == HVAC_AUTO_ON_AREA_ROW1_RIGHT) {
            Assert.assertEquals(value, halValueRow1Right);
        } else if (area == HVAC_AUTO_ON_AREA_ROW2_RIGHT) {
            Assert.assertEquals(value, halValueRow2Right);
        }

    }

    public void testHvacAutoOnGet(int area, boolean value) {
        Log.d(TAG, "testHvacAutoOnGet area：" + area + " value: " + value);
        mCarPropertyMgr.setBooleanProperty(HVAC_AUTO_ON, area, value);

        lockWait(area);

        boolean isHvacAutoOn = mCarPropertyMgr.getBooleanProperty(HVAC_AUTO_ON, area);
        Assert.assertEquals(value, isHvacAutoOn);
    }

    public void setHvacAutorOnAvail(int avail, int onOff, int area) {
        Log.d(TAG, "setHvacAutorOnAvail area:" + area + " avail：" + avail + " onoff:" + onOff);
        IpcpClient ipcpClient = new IpcpClient();
        String availabilityIndex = "";
        String dataIndex = "";
        if (area == HVAC_AUTO_ON_AREA_ROW1) {
            availabilityIndex = "paclauto.availability";
            dataIndex = "paclauto.data";
        } else if (area == HVAC_AUTO_ON_AREA_ROW2) {
            availabilityIndex = "paclsecautosw.availability";
            dataIndex = "paclsecautosw.data";
        } else if (area == HVAC_AUTO_ON_AREA_ROW1_RIGHT) {
            availabilityIndex = "paclautori.availability";
            dataIndex = "paclautori.data";
        } else if (area == HVAC_AUTO_ON_AREA_ROW2_RIGHT) {
            availabilityIndex = "paclsecautoswri.availability";
            dataIndex = "paclsecautoswri.data";
        }
        String[] config_indexs = {availabilityIndex, dataIndex};
        int[] values = {avail, onOff};
        boolean bb = ipcpClient.setClimaSignal(SERVICE_ID_CLIMATE, OP_ID_CLIMATE, config_indexs,  values);
        Assert.assertTrue(bb);
        lockWait(area);
    }


    private static void setConfig(int OperId) {
        IpcpClient ipcpClient = new IpcpClient();
        int climateOperId[] = {OperId};
        ipcpClient.setConfig(SERVICE_ID_CLIMATE, climateOperId);
    }

}
